package core.util;

import core.model.mail.Context;
import core.model.mail.Message;
import core.model.newgame.NewGame;
import core.model.newgame.NewGameRace;
import org.apache.commons.lang.StringUtils;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import java.util.*;

public class Parser {

    private final static String FIRST_HEADER = "Report for Galaxy PLUS";

    private final static String UNIDENTIFIED_PLANETS = "Unidentified Planets";

    private final static String YOUR_PLANETS = "Your Planets";
    private final static String YOUR_VOTE = "Your vote";

    private final static String YOUR_SHIP_TYPES = "Your Ship Types";
    private final static String YOUR_SHIP_TYPES_HEADER = "NDAWSCM";

    private final static String YOUR_GROUPS = "Your Groups";
    private final static String YOUR_GROUPS_HEADER = "G#TDWSCTQDFRPML";

    private final static String UNINHABITED_PLANET = "Uninhabited Planets";
    private final static String UNINHABITED_PLANET_HEADER = "#XYNSR$M";


    private final static String YOUR_PLANETS_HEADER = "#XYNSPIRP$MCL";
    private final static String UNIDENTIFIED_PLANETS_HEADER = "#XY";
    private final static String RACES_HEADER = "NDWSCPI#RV";

    private final static String BATTLE = "Battle at";
    private final static String BATTLE_PROTOCOL = "Battle Protocol";
    private final static String BATTLE_GROUP_HEADER = "#TDWSCTQL";

    private final static String PLANETS = "Planets";
    private final static String PLANETS_HEADER = "#XYNSPIRP$MCL";

    private final static String GROUPS = "Groups";
    private final static String GROUPS_HEADER = "#TDWSCTQDPM";

    private final static String STATUS_OF_PLAYER = "Status of Players";
    private final static String PARTY_INFO = "Size:";

    private final static String BAD_ELEMENT = "&#13;";

    public Map<String, String> parseMessages(Document response) {
        Map<String, String> result = new HashMap<String, String>();

        NodeList nodeList = response.getElementsByTagName("file");

        for (int index = 0; index < nodeList.getLength(); index++) {
            Node node = nodeList.item(index);

            String fileId = getAttributeValue(node.getAttributes(), "name");
            String body = getMessageBody(node);

            result.put(fileId, body);
        }

        return result;
    }

    private String getMessageBody(Node node) {

        NodeList nodeList = node.getChildNodes();

        if (nodeList == null || nodeList.getLength() != 1) {
            // todo handle
        }

        return nodeList.item(0).getNodeValue();
    }


    public Context parseContext(Document response) {

        Logger.info("Parser", "Parsing context...");

        Context context = new Context();

        parseInfo(response, context);
        parseMessages(response, context, Message.MessageType.BROADCAST);
        parseMessages(response, context, Message.MessageType.PRIVATE);

        Logger.info("Parser", "Parsing context... COMPLETE");
        Logger.info("Parser", "\tPrivates: " + context.getPrivates().size());
        Logger.info("Parser", "\tBroadcasts: " + context.getBroadcasts().size());

        return context;
    }


    private void parseInfo(Document response, Context context) {

        NodeList nodeList = response.getElementsByTagName("info");
        if (nodeList == null || nodeList.getLength() != 1) {
            // todo logging
            return;
        }

        Node node = nodeList.item(0);
        NamedNodeMap attributes = node.getAttributes();

        context.setTurn(Integer.valueOf(getAttributeValue(attributes, "turn")));
    }


    private void parseMessages(Document response, Context context, Message.MessageType messageType) {

        //todo null
        NodeList nodeList = response.getElementsByTagName((messageType.getElementId()));

        if (nodeList == null || nodeList.getLength() != 1) {
            return;
        }

        nodeList = nodeList.item(0).getChildNodes();

        for (int index = 0; index < nodeList.getLength(); index++) {
            Node node = nodeList.item(index);
            NamedNodeMap attributes = node.getAttributes();

            Message message = new Message();
            message.setFile(getAttributeValue(attributes, "file"));
            message.setTurn(Integer.valueOf(getAttributeValue(attributes, "turn")));
            message.setFrom(getAttributeValue(attributes, "race"));

            context.addMessage(message, messageType);
        }

    }


/*
    public Report parseReport(String reportAsString) {

        Logger.info("Parser", "Parsing report...");
        long startTime = System.currentTimeMillis();

        int turn = -1;
        String game = StringUtils.EMPTY;
        String race = StringUtils.EMPTY;
        List<Planet> unidentifiedPlanets = new ArrayList<Planet>();
        List<Planet> yourPlanets = new ArrayList<Planet>();
        List<Group> yourGroups = new ArrayList<Group>();
        List<Race> races = new ArrayList<Race>();
        List<Group> alienGroups = new ArrayList<Group>();
        List<Battle> battles = new ArrayList<Battle>();
        List<Planet> uninhabitedPlanets = new ArrayList<Planet>();
        List<Planet> alienPlanets = new ArrayList<Planet>();
        List<ShipType> yourShipTypes = new ArrayList<ShipType>();

        List<String> responseItems = Arrays.asList(StringUtils.split(reportAsString, "\r"));


        for (Iterator it = responseItems.iterator(); it.hasNext();) {
            String element = getNextNotEmptyLine(it, StringUtils.EMPTY);

            String line = StringUtils.trim(element);

            // --- First Header ---
            if (StringUtils.contains(line, FIRST_HEADER)) {
                turn = parseTurn(line);
            }

            if (StringUtils.contains(line, FIRST_HEADER)) {
                game = parseGame(line);
            }

            if (StringUtils.contains(line, FIRST_HEADER)) {
                race = parseRace(line);
            }

            // --- Your ship types ---
            if (StringUtils.contains(line, YOUR_SHIP_TYPES)) {
                parseYourShipTypes(yourShipTypes, it);
            }

            // --- Alien planets ---
            if (StringUtils.contains(line, PLANETS)
                    && !StringUtils.contains(line, UNINHABITED_PLANET)
                    && !StringUtils.contains(line, YOUR_PLANETS)
                    && !StringUtils.contains(line, UNIDENTIFIED_PLANETS)
                    && !StringUtils.contains(line, PARTY_INFO)) {
                parseAlienPlanets(alienPlanets, it, line);
            }

            // --- Uninhabited planets ---
            if (StringUtils.contains(line, UNINHABITED_PLANET)) {
                parseUninhabitedPlanets(uninhabitedPlanets, it);
            }

            // --- Battle ---
            if (StringUtils.contains(line, BATTLE)) {
                parseBattle(battles, it, line);
            }

            // --- Alien groups ---
            if (!StringUtils.contains(line, YOUR_GROUPS)
                    && StringUtils.contains(line, GROUPS)) {
                parseAlienGroups(alienGroups, it, line);
            }

            // --- Your groups ---
            if (StringUtils.contains(line, YOUR_GROUPS)) {
                parseYourGroups(yourGroups, it);
            }

            // --- Your planets ---
            if (StringUtils.contains(line, YOUR_PLANETS)) {
                parseYourPlanets(yourPlanets, it);
            }

            // --- Races ---
            if (StringUtils.contains(line, STATUS_OF_PLAYER)) {
                parseRaces(races, it);
            }

            // --- Unidentified Planets ---
            if (StringUtils.contains(line, UNIDENTIFIED_PLANETS)) {
                parseUnidentifiedPlanets(unidentifiedPlanets, it);
            }
        }


        Report report = new Report();
        report.setUnidentifiedPlanets(unidentifiedPlanets);
        report.setRaces(races);
        report.setYourPlanets(yourPlanets);
        report.setYourGroups(yourGroups);
        report.setBattles(battles);
        report.setAlienGroups(alienGroups);
        report.setUninhabitedPlanets(uninhabitedPlanets);
        report.setAlienPlanets(alienPlanets);
        report.setTurn(turn);
        report.setGame(game);
        report.setRace(race, races);
        report.setYourShipTypes(yourShipTypes);

        long endTime = System.currentTimeMillis();

        Logger.info("Parser", "Parsing report... COMPLETE in " + (endTime - startTime) + "ms");
        return report;
    }
*/

/*
    private void parseYourShipTypes(List<ShipType> yourGroupTypes, Iterator it) {
        String elementShipType = getNextNotEmptyLine(it, YOUR_SHIP_TYPES_HEADER);
        int count = 0;
        do {
            String[] shipTypeSplitted = StringUtils.split(elementShipType);

            String type = shipTypeSplitted[0];
            double drive = Double.valueOf(shipTypeSplitted[1]);
            int arm = Integer.valueOf(shipTypeSplitted[2]);
            double weapon = Double.valueOf(shipTypeSplitted[3]);
            double shield = Double.valueOf(shipTypeSplitted[4]);
            double cargo = Double.valueOf(shipTypeSplitted[5]);
            double mass = Double.valueOf(shipTypeSplitted[6]);

            ShipType shipType = new ShipType(type, drive, arm, weapon, shield, cargo, mass);


            yourGroupTypes.add(shipType);
            count++;

            elementShipType = (String) it.next();

        } while (!isEnd(it, elementShipType));

        Logger.info("Parser", "Loading your ship types complete. Ship types loaded: " + count);

    }
*/

/*
    private String parseRace(String line) {
        // <race> Report for Galaxy PLUS <game> Turn <turn> <>date
        String[] lines = StringUtils.split(line);
        return lines[0];
    }

    private String parseGame(String line) {
        // <race> Report for Galaxy PLUS <game> Turn <turn> <>date
        String[] lines = StringUtils.split(line);
        return lines[5];
    }

    private int parseTurn(String line) {
        // <race> Report for Galaxy PLUS <game> Turn <turn> <>date
        String[] lines = StringUtils.split(line);
        return Integer.valueOf(lines[7]);
    }

    private void parseAlienPlanets(List<Planet> alienPlanets, Iterator it, String line) {

        String[] lines = StringUtils.split(line);
        String owner = lines[0];

        String elementPlanet = getNextNotEmptyLine(it, PLANETS_HEADER);
        int count = 0;
        do {

            String[] planetInfo = StringUtils.split(elementPlanet);

            int number = Integer.valueOf(planetInfo[0]);
            double x = Double.valueOf(planetInfo[1]);
            double y = Double.valueOf(planetInfo[2]);
            String name = planetInfo[3];
            double size = Double.valueOf(planetInfo[4]);
            double population = Double.valueOf(planetInfo[5]);
            double industry = Double.valueOf(planetInfo[6]);
            double resources = Double.valueOf(planetInfo[7]);
            String production = planetInfo[8];
            double industryStock = Double.valueOf(planetInfo[9]);
            double materialStock = Double.valueOf(planetInfo[10]);
            double colonists = Double.valueOf(planetInfo[11]);
            double freeIndustryPotential = Double.valueOf(planetInfo[12]);


            Planet planet = new Planet(number, x, y, PlanetType.ALIEN_PLANET);
            planet.setOwner(owner);
            planet.setName(name);
            planet.setSize(size);
            planet.setPopulation(population);
            planet.setIndustry(industry);
            planet.setResources(resources);
            planet.setProduction(production);
            planet.setIndustryStock(industryStock);
            planet.setMaterialStock(materialStock);
            planet.setColonists(colonists);
            planet.setFreeIndustryPotential(freeIndustryPotential);

            alienPlanets.add(planet);
            count++;

            elementPlanet = (String) it.next();

        } while (!isEnd(it, elementPlanet));

        Logger.info("Parser", "Loading alien planets complete. Planets loaded: " + count);

    }

    private void parseUninhabitedPlanets(List<Planet> uninhabitedPlanets, Iterator it) {
        String elementPlanet = getNextNotEmptyLine(it, UNINHABITED_PLANET_HEADER);
        int count = 0;
        do {

            String[] planetInfo = StringUtils.split(elementPlanet);

            int number = Integer.valueOf(planetInfo[0]);
            double x = Double.valueOf(planetInfo[1]);
            double y = Double.valueOf(planetInfo[2]);
            String name = planetInfo[3];
            double size = Double.valueOf(planetInfo[4]);
            double resources = Double.valueOf(planetInfo[5]);
            double industryStock = Double.valueOf(planetInfo[6]);
            double materialStock = Double.valueOf(planetInfo[7]);

            Planet planet = new Planet(number, x, y, PlanetType.UNINHABITED_PLANET);
            planet.setName(name);
            planet.setSize(size);
            planet.setResources(resources);
            planet.setIndustryStock(industryStock);
            planet.setMaterialStock(materialStock);

            uninhabitedPlanets.add(planet);
            count++;

            elementPlanet = (String) it.next();

        } while (!isEnd(it, elementPlanet));

        Logger.info("Parser", "Loading uninhabited planets complete. Planets loaded: " + count);
    }

    private void parseBattle(List<Battle> battles, Iterator it, String line) {
        String[] lines = StringUtils.split(line, "()#");

        Battle battle = new Battle();
        battle.setPlanetNumber(Integer.valueOf(lines[1]));
        battle.setPlanetName(lines[2]);

        boolean isEnd = false;
        do {
            String element = getNextNotEmptyLine(it, StringUtils.EMPTY);

            if (StringUtils.contains(element, GROUPS)) {
                parseGroupsInBattle(battle.getGroups(), it, element);
            }

            if (StringUtils.contains(element, BATTLE_PROTOCOL)) {
                isEnd = true;
                parseBattleProtocol(battle.getProtocol(), it);
            }

        } while (!isEnd);

        battles.add(battle);
    }

    private void parseBattleProtocol(List<String> protocol, Iterator it) {
        String element = getNextNotEmptyLine(it, StringUtils.EMPTY);
        do {
            protocol.add(StringUtils.trim(element));
            element = getNextNotEmptyLine(it, StringUtils.EMPTY);
        } while (isEnd(it, element));
    }

    public void parseGroupsInBattle(List<Group> groups, Iterator it, String line) {

        String[] lines = StringUtils.split(line);
        String owner = lines[0];

        String element = getNextNotEmptyLine(it, BATTLE_GROUP_HEADER);
        int counts = 0;
        do {

            String[] info = StringUtils.split(element);
            int count = Integer.valueOf(info[0]);
            String type = info[1];
            Double drive = Double.valueOf(info[2]);
            Double weapon = Double.valueOf(info[3]);
            Double shield = Double.valueOf(info[4]);
            Double cargo = Double.valueOf(info[5]);

            Group group = new Group();
            group.setOwner(owner);
            group.setGroupType(GroupType.GROUP_IN_BATTLE);
            group.setCount(count);
            group.setType(type);
            group.setDrive(new Technology(Technology.TechnologyType.DRIVE, drive));
            group.setWeapon(new Technology(Technology.TechnologyType.WEAPON, weapon));
            group.setShield(new Technology(Technology.TechnologyType.SHIELD, shield));
            group.setCargo(new Technology(Technology.TechnologyType.CARGO, cargo));

            groups.add(group);
            counts++;

            element = (String) it.next();

        } while (!isEnd(it, element));

        Logger.info("Parser", "Loading groups complete. Groups loaded: " + counts);

    }


    public void parseAlienGroups(List<Group> alienGroups, Iterator it, String line) {

        String[] lines = StringUtils.split(line);
        String owner = lines[0];

        String element = getNextNotEmptyLine(it, GROUPS_HEADER);
        int counts = 0;
        do {

            String[] info = StringUtils.split(element);
            int count = Integer.valueOf(info[0]);
            String type = info[1];
            Double drive = Double.valueOf(info[2]);
            Double weapon = Double.valueOf(info[3]);
            Double shield = Double.valueOf(info[4]);
            Double cargo = Double.valueOf(info[5]);
            String destination = info[8];

            Group group = new Group();
            group.setOwner(owner);
            group.setGroupType(GroupType.ALIEN_GROUP);
            group.setCount(count);
            group.setType(type);
            group.setDrive(new Technology(Technology.TechnologyType.DRIVE, drive));
            group.setWeapon(new Technology(Technology.TechnologyType.WEAPON, weapon));
            group.setShield(new Technology(Technology.TechnologyType.SHIELD, shield));
            group.setCargo(new Technology(Technology.TechnologyType.CARGO, cargo));
            group.setDestination(destination);

            alienGroups.add(group);
            counts++;

            element = (String) it.next();

        } while (!isEnd(it, element));

        Logger.info("Parser", "Loading your groups complete. Groups loaded: " + counts);

    }

    private void parseYourGroups(List<Group> yourGroups, Iterator it) {
        String element = getNextNotEmptyLine(it, YOUR_GROUPS_HEADER);
        int counts = 0;
        do {

            String[] info = StringUtils.split(element);
            int number = Integer.valueOf(info[0]);
            int count = Integer.valueOf(info[1]);
            String type = info[2];
            Double drive = Double.valueOf(info[3]);
            Double weapon = Double.valueOf(info[4]);
            Double shield = Double.valueOf(info[5]);
            Double cargo = Double.valueOf(info[6]);
            String destination = info[9];
            String state = info[15];

            Group group = new Group();
            group.setGroupType(GroupType.YOUR_GROUP);
            group.setNumber(number);
            group.setCount(count);
            group.setType(type);
            group.setDrive(new Technology(Technology.TechnologyType.DRIVE, drive));
            group.setWeapon(new Technology(Technology.TechnologyType.WEAPON, weapon));
            group.setShield(new Technology(Technology.TechnologyType.SHIELD, shield));
            group.setCargo(new Technology(Technology.TechnologyType.CARGO, cargo));
            group.setDestination(destination);
            group.setState(state);

            yourGroups.add(group);
            counts++;

            element = (String) it.next();

        } while (!isEnd(it, element));

        Logger.info("Parser", "Loading your groups complete. Groups loaded: " + counts);
    }


    */

    /**
     * Parsing "Your planets".
     *//*

    private void parseYourPlanets(List<Planet> planets, Iterator it) {
        String elementPlanet = getNextNotEmptyLine(it, YOUR_PLANETS_HEADER);
        int count = 0;
        do {

            String[] planetInfo = StringUtils.split(elementPlanet);

            int number = Integer.valueOf(planetInfo[0]);
            double x = Double.valueOf(planetInfo[1]);
            double y = Double.valueOf(planetInfo[2]);
            String name = planetInfo[3];
            double size = Double.valueOf(planetInfo[4]);
            double population = Double.valueOf(planetInfo[5]);
            double industry = Double.valueOf(planetInfo[6]);
            double resources = Double.valueOf(planetInfo[7]);
            String production = planetInfo[8];
            double industryStock = Double.valueOf(planetInfo[9]);
            double materialStock = Double.valueOf(planetInfo[10]);
            double colonists = Double.valueOf(planetInfo[11]);
            double freeIndustryPotential = Double.valueOf(planetInfo[12]);


            Planet planet = new Planet(number, x, y, PlanetType.YOUR_PLANET);
            planet.setName(name);
            planet.setSize(size);
            planet.setPopulation(population);
            planet.setIndustry(industry);
            planet.setResources(resources);
            planet.setProduction(production);
            planet.setIndustryStock(industryStock);
            planet.setMaterialStock(materialStock);
            planet.setColonists(colonists);
            planet.setFreeIndustryPotential(freeIndustryPotential);

            planets.add(planet);
            count++;

            elementPlanet = (String) it.next();

        } while (!isEnd(it, elementPlanet));

        Logger.info("Parser", "Loading your planets complete. Planets loaded: " + count);

    }
*/

/*
    private void parseUnidentifiedPlanets(List<Planet> planets, Iterator it) {
        String elementPlanet = getNextNotEmptyLine(it, UNIDENTIFIED_PLANETS_HEADER);
        int count = 0;
        do {

            String[] planetInfo = StringUtils.split(elementPlanet);

            int number = Integer.valueOf(planetInfo[0]);
            double x = Double.valueOf(planetInfo[1]);
            double y = Double.valueOf(planetInfo[2]);

            Planet planet = new Planet(number, x, y, PlanetType.UNIDENTIFIED_PLANET);

            planets.add(planet);
            count++;

            elementPlanet = (String) it.next();

        } while (!isEnd(it, elementPlanet));

        Logger.info("Parser", "Loading unidentified planets complete. Planets loaded: " + count);
    }

    private void parseRaces(List<Race> races, Iterator it) {
        String elementRace = getNextNotEmptyLine(it, RACES_HEADER);
        do {
            String[] raceInfo = StringUtils.split(elementRace);

            String name = raceInfo[0];
            Double drive = Double.valueOf(raceInfo[1]);
            Double weapon = Double.valueOf(raceInfo[2]);
            Double shield = Double.valueOf(raceInfo[3]);
            Double cargo = Double.valueOf(raceInfo[4]);
            RaceState state = RaceState.getState(raceInfo[8]);


            Race race = new Race(name);
            race.setDrive(new Technology(Technology.TechnologyType.DRIVE, drive));
            race.setWeapon(new Technology(Technology.TechnologyType.WEAPON, weapon));
            race.setShield(new Technology(Technology.TechnologyType.SHIELD, shield));
            race.setCargo(new Technology(Technology.TechnologyType.CARGO, cargo));
            race.setState(state);

            races.add(race);

            elementRace = (String) it.next();

        } while (!isEnd(it, elementRace));

        Logger.info("Parser", "Loading races complete. Races loaded: " + races.size());
    }
*/
    private boolean isEnd(Iterator it, String text) {
        return !it.hasNext() || StringUtils.isEmpty(StringUtils.trim(text)) || BAD_ELEMENT.equals(text);
    }

    private String getNextNotEmptyLine(Iterator it, String strToSkip) {
        String element;
        String tempElement;
        do {
            element = (String) it.next();

            tempElement = StringUtils.replace(element, " ", "");
        } while (it.hasNext()
                && (StringUtils.isEmpty(StringUtils.trim(element))
                || strToSkip.equals(StringUtils.trim(tempElement))
                || BAD_ELEMENT.equals(element)));
        return element;
    }

    public String parseResponseError(Document document) {
        if (document == null) {
            return StringUtils.EMPTY;
        }

        NodeList nodeList = document.getElementsByTagName("error");

        if (nodeList == null ||
                nodeList.getLength() != 1 ||
                nodeList.item(0).getChildNodes() == null ||
                nodeList.item(0).getChildNodes().getLength() != 1) {
            return StringUtils.EMPTY;
        }

        return  nodeList.item(0).getChildNodes().item(0).getNodeValue();
    }

    public List<NewGame> loadGames(Document document) {
        List<NewGame> newGames = new ArrayList<NewGame>();

        NodeList nodeList = document.getElementsByTagName("game");
        for (int indexGame = 0; indexGame < nodeList.getLength(); indexGame++) {
            Node node = nodeList.item(indexGame);


            NewGame newGame = new NewGame();

            NamedNodeMap attributes = node.getAttributes();
            newGame.setName(getAttributeValue(attributes, "name"));
            newGame.setTurns(Integer.valueOf(getAttributeValue(attributes, "turns")));
            newGame.setPlayers(Integer.valueOf(getAttributeValue(attributes, "players")));
            newGame.setQuickStart("Yes".equalsIgnoreCase(getAttributeValue(attributes, "quick_start")));
            newGame.setPrivateGame("Yes".equalsIgnoreCase(getAttributeValue(attributes, "private")));
            newGame.setHr("Yes".equalsIgnoreCase(getAttributeValue(attributes, "hr")));


            for (int indexRace = 0; indexRace < node.getChildNodes().getLength(); indexRace++) {
                Node subnode = node.getChildNodes().item(indexRace);
                String nodeName = subnode.getNodeName();

                if ("races".equalsIgnoreCase(nodeName)) {
                    loadNewGameRaces(subnode, newGame);
                }

                if ("legend".equalsIgnoreCase(nodeName)) {
                    loadNewGameLegend(subnode, newGame);
                }


            }

            newGames.add(newGame);
        }

        return newGames;
    }

    private void loadNewGameLegend(Node subnode, NewGame newGame) {
        NodeList nodeList = subnode.getChildNodes();

        for (int index = 0; index < nodeList.getLength(); index++) {
            Node node = nodeList.item(index);

            java.lang.String[] options = StringUtils.split(node.getNodeValue(), "\n");
            for (String option : options) {
                newGame.addOption(option);
            }
        }
    }

    private void loadNewGameRaces(Node subnode, NewGame newGame) {
        NodeList races = subnode.getChildNodes();

        for (int index = 0; index < races.getLength(); index++) {
            Node race = races.item(index);
            NamedNodeMap attibutes = race.getAttributes();

            NewGameRace newGameRace = new NewGameRace();
            newGameRace.setName(getAttributeValue(attibutes, "name"));
            newGameRace.setAccepted("Yes".equalsIgnoreCase(getAttributeValue(attibutes, "accepted")));

            newGame.addRace(newGameRace);
        }
    }

    private String getAttributeValue(NamedNodeMap attributes, String attribute) {
        Node node = attributes.getNamedItem(attribute);

        if (node == null) {
            return StringUtils.EMPTY;
        }

        return node.getNodeValue();
    }

    public List<String> parseRaces(Document response) {
        List<String> result = new ArrayList<String>();

        if (response == null) {
            return result;
        }

        NodeList nodeList = response.getElementsByTagName("race");
        for (int index = 0; index < nodeList.getLength(); index++) {
            Node node = nodeList.item(index);
            String name = node.getAttributes().getNamedItem("name").getNodeValue();
            result.add(name);
        }

        return result;
    }
}